//---------------------------------------------------------------------------------------------------
template <class Real>
Vector4<Real>::Vector4()
{

}
//---------------------------------------------------------------------------------------------------
template <class Real>
Vector4<Real>::Vector4(Real fX, Real fY, Real fZ, Real fW)
{
	m_afTuple[0] = fX;
	m_afTuple[1] = fY;
	m_afTuple[2] = fZ;
	m_afTuple[3] = fW;
}
//---------------------------------------------------------------------------------------------------
template <class Real>
Vector4<Real>::Vector4(const Real* afTuple)
{
	m_afTuple[0] = afTuple[0];
	m_afTuple[1] = afTuple[1];
	m_afTuple[2] = afTuple[2];
	m_afTuple[3] = afTuple[3];
}
//---------------------------------------------------------------------------------------------------
template <class Real>
Vector4<Real>::Vector4(const Vector4& rkVector4)
{
	m_afTuple[0] = rkVector4.m_afTuple[0];
	m_afTuple[1] = rkVector4.m_afTuple[1];
	m_afTuple[2] = rkVector4.m_afTuple[2];
	m_afTuple[3] = rkVector4.m_afTuple[3];
}
//---------------------------------------------------------------------------------------------------
template <class Real>
Vector4<Real>::Vector4(const Vector3<Real>& rkV3, Real w)
{
	// construct vector4 from vector3
	m_afTuple[0] = rkV3.X();
	m_afTuple[1] = rkV3.Y();
	m_afTuple[2] = rkV3.Z();
	m_afTuple[3] = w;
}
//---------------------------------------------------------------------------------------------------
template <class Real>
int Vector4<Real>::CompareArrays(const Vector4& rkV) const
{
	return memcmp(m_afTuple, rkV.m_afTuple, 4*sizeof(Real));
}
//---------------------------------------------------------------------------------------------------
template <class Real>
bool Vector4<Real>::operator== (const Vector4& rkV) const
{
	return CompareArrays(rkV) == 0;
}
//---------------------------------------------------------------------------------------------------
template <class Real>
bool Vector4<Real>::operator!= (const Vector4& rkV) const
{
	return CompareArrays(rkV) != 0;
}
//---------------------------------------------------------------------------------------------------
template <class Real>
bool Vector4<Real>::operator< (const Vector4& rkV) const
{
	return CompareArrays(rkV) < 0;
}
//---------------------------------------------------------------------------------------------------
template <class Real>
bool Vector4<Real>::operator<= (const Vector4& rkV) const
{
	return CompareArrays(rkV) <= 0;
}
//---------------------------------------------------------------------------------------------------
template <class Real>
bool Vector4<Real>::operator> (const Vector4& rkV) const
{
	return CompareArrays(rkV) > 0;
}
//---------------------------------------------------------------------------------------------------
template <class Real>
bool Vector4<Real>::operator>= (const Vector4& rkV) const
{
	return CompareArrays(rkV) >= 0;
}
//---------------------------------------------------------------------------------------------------
//---------------------------------------------------------------------------------------------------
template <class Real>
inline Vector4<Real>::operator Real* ()
{
	return m_afTuple;
}
//---------------------------------------------------------------------------------------------------
template <class Real>
inline Vector4<Real>::operator const Real* () const
{
	return m_afTuple;
}
//---------------------------------------------------------------------------------------------------
template <class Real>
inline Real Vector4<Real>::operator[] (int i) const
{
	if (i < 0)
	{
		i = 0;
	}
	if (i > 3)
	{
		i = 3;
	}
	return m_afTuple[i];
}
//---------------------------------------------------------------------------------------------------
template <class Real>
inline Real& Vector4<Real>::operator[] (int i)
{
	if (i < 0)
	{
		i = 0;
	}
	if (i > 3)
	{
		i = 3;
	}
	return m_afTuple[i];
}
//---------------------------------------------------------------------------------------------------
template <class Real>
inline Real Vector4<Real>::X() const
{
	return m_afTuple[0];
}
//---------------------------------------------------------------------------------------------------
template <class Real>
inline Real& Vector4<Real>::X()
{
	return m_afTuple[0];
}
//---------------------------------------------------------------------------------------------------
template <class Real>
inline Real Vector4<Real>::Y() const
{
	return m_afTuple[1];
}
//---------------------------------------------------------------------------------------------------
template <class Real>
inline Real& Vector4<Real>::Y()
{
	return m_afTuple[1];
}
//---------------------------------------------------------------------------------------------------
template <class Real>
inline Real Vector4<Real>::Z() const
{
	return m_afTuple[2];
}
//---------------------------------------------------------------------------------------------------
template <class Real>
inline Real& Vector4<Real>::Z()
{
	return m_afTuple[2];
}
//---------------------------------------------------------------------------------------------------
template <class Real>
inline Real Vector4<Real>::W() const
{
	return m_afTuple[3];
}
//---------------------------------------------------------------------------------------------------
template <class Real>
inline Real& Vector4<Real>::W()
{
	return m_afTuple[3];
}
//---------------------------------------------------------------------------------------------------
template <class Real>
inline Vector4<Real>& Vector4<Real>::operator= (const Vector4& rkV)
{
	m_afTuple[0] = rkV.m_afTuple[0];
	m_afTuple[1] = rkV.m_afTuple[1];
	m_afTuple[2] = rkV.m_afTuple[2];
	m_afTuple[3] = rkV.m_afTuple[3];
	return *this;
}
//---------------------------------------------------------------------------------------------------
template <class Real>
inline Vector4<Real> Vector4<Real>::operator+ (const Vector4& rkV) const
{
	return Vector4(
		m_afTuple[0] + rkV.m_afTuple[0],
		m_afTuple[1] + rkV.m_afTuple[1],
		m_afTuple[2] + rkV.m_afTuple[2],
		m_afTuple[3] + rkV.m_afTuple[3]);
}
//---------------------------------------------------------------------------------------------------
template <class Real>
inline Vector4<Real> Vector4<Real>::operator- (const Vector4& rkV) const
{
	return Vector4(
		m_afTuple[0] - rkV.m_afTuple[0],
		m_afTuple[1] - rkV.m_afTuple[1],
		m_afTuple[2] - rkV.m_afTuple[2],
		m_afTuple[3] - rkV.m_afTuple[3]);
}
//---------------------------------------------------------------------------------------------------
template <class Real>
inline Vector4<Real> Vector4<Real>::operator* (const Real fScalar) const
{
	return Vector4(
		m_afTuple[0] * fScalar,
		m_afTuple[1] * fScalar,
		m_afTuple[2] * fScalar,
		m_afTuple[3] * fScalar);
}
//---------------------------------------------------------------------------------------------------
template <class Real>
inline Vector4<Real> operator* (Real fScalar, const Vector4<Real>& rkV)
{
	return Vector4(
		fScalar * rkV[0],
		fScalar * rkV[1],
		fScalar * rkV[2],
		fScalar * rkV[3]);
}
//---------------------------------------------------------------------------------------------------
template <class Real>
inline Vector4<Real> Vector4<Real>::operator/ (const Real fScalar) const
{
	Vector4 kOut;
	if (fScalar != 0.0f)
	{
		Real fInv = 1.0f / fScalar;
		kOut.m_afTuple[0] = m_afTuple[0] * fInv;
		kOut.m_afTuple[1] = m_afTuple[1] * fInv;
		kOut.m_afTuple[2] = m_afTuple[2] * fInv;
		kOut.m_afTuple[3] = m_afTuple[3] * fInv;
	}
	else
	{
		kOut.m_afTuple[0] = FLT_MAX;
		kOut.m_afTuple[1] = FLT_MAX;
		kOut.m_afTuple[2] = FLT_MAX;
		kOut.m_afTuple[3] = FLT_MAX;
	}
	return kOut;
}
//---------------------------------------------------------------------------------------------------
template <class Real>
inline Vector4<Real> Vector4<Real>::operator- () const
{
	return Vector4(
		-m_afTuple[0],
		-m_afTuple[1],
		-m_afTuple[2],
		-m_afTuple[3]);
}
//---------------------------------------------------------------------------------------------------
template <class Real>
inline Vector4<Real>& Vector4<Real>::operator += (const Vector4& rkV)
{
	m_afTuple[0] += rkV.m_afTuple[0];
	m_afTuple[1] += rkV.m_afTuple[1];
	m_afTuple[2] += rkV.m_afTuple[2];
	m_afTuple[3] += rkV.m_afTuple[3];
	return *this;
}
//---------------------------------------------------------------------------------------------------
template <class Real>
inline Vector4<Real>& Vector4<Real>::operator -= (const Vector4& rkV)
{
	m_afTuple[0] -= rkV.m_afTuple[0];
	m_afTuple[1] -= rkV.m_afTuple[1];
	m_afTuple[2] -= rkV.m_afTuple[2];
	m_afTuple[3] -= rkV.m_afTuple[3];
	return *this;
}
//---------------------------------------------------------------------------------------------------
template <class Real>
inline Vector4<Real>& Vector4<Real>::operator *= (Real fScalar)
{
	m_afTuple[0] *= fScalar;
	m_afTuple[1] *= fScalar;
	m_afTuple[2] *= fScalar;
	m_afTuple[3] *= fScalar;
	return *this;
}
//---------------------------------------------------------------------------------------------------
template <class Real>
inline Vector4<Real>& Vector4<Real>::operator /= (Real fScalar)
{
	if (fScalar != 0.0f)
	{
		Real fInv = 1.0f / fScalar;
		m_afTuple[0] *= fInv;
		m_afTuple[1] *= fInv;
		m_afTuple[2] *= fInv;
		m_afTuple[3] *= fInv;
	}
	else
	{
		m_afTuple[0] = FLT_MAX;
		m_afTuple[1] = FLT_MAX;
		m_afTuple[2] = FLT_MAX;
		m_afTuple[3] = FLT_MAX;
	}
	return *this;
}
//---------------------------------------------------------------------------------------------------
template <class Real>
inline Real Vector4<Real>::Length() const
{
	return sqrt(
		m_afTuple[0]*m_afTuple[0] +
		m_afTuple[1]*m_afTuple[1] +
		m_afTuple[2]*m_afTuple[2] +
		m_afTuple[3]*m_afTuple[3]);
}
//---------------------------------------------------------------------------------------------------
template <class Real>
inline Real Vector4<Real>::SquaredLength() const
{
	return (		
		m_afTuple[0]*m_afTuple[0] +
		m_afTuple[1]*m_afTuple[1] +
		m_afTuple[2]*m_afTuple[2] +
		m_afTuple[3]*m_afTuple[3]);
}
//---------------------------------------------------------------------------------------------------
template <class Real>
inline Real Vector4<Real>::Dot(const Vector4& rkV) const
{
	return (
		m_afTuple[0]*rkV.m_afTuple[0] +
		m_afTuple[1]*rkV.m_afTuple[1] +
		m_afTuple[2]*rkV.m_afTuple[2] +
		m_afTuple[3]*rkV.m_afTuple[3]);
}
//---------------------------------------------------------------------------------------------------
template <class Real>
inline Real Vector4<Real>::Normalize()
{
	Real fLength = Length();
	if (fLength > 1e-06f)
	{
		Real fInv = 1.0f / fLength;
		m_afTuple[0] *= fInv;
		m_afTuple[1] *= fInv;
		m_afTuple[2] *= fInv;
		m_afTuple[3] *= fInv;
	}
	else
	{
		fLength = 0.0f;
		m_afTuple[0] = 0.0f;
		m_afTuple[1] = 0.0f;
		m_afTuple[2] = 0.0f;
		m_afTuple[3] = 0.0f;
	}

	return fLength;
}
//---------------------------------------------------------------------------------------------------
template <class Real>
void Vector4<Real>::Print()
{
	printf("%6f, %6f, %6f, %6f\n",m_afTuple[0],m_afTuple[1],m_afTuple[2], m_afTuple[3]);
}
//---------------------------------------------------------------------------------------------------